package com.yeskery.nut.core;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * 抽象controller动态代理处理对象
 * @author sprout
 * 2022-05-14 14:55
 */
public abstract class AbstractControllerInvocationHandler implements InvocationHandler {

    /** 请求方法开始名称 */
    private static final String REQUEST_METHOD_START_NAME = "do";

    /** 主请求方法名称 */
    private static final String DO_REQUEST_METHOD_NAME = "doRequest";

    /** 目标对象 */
    private final Object target;

    /**
     * 构建controller动态代理处理对象
     * @param target 目标对象
     */
    public AbstractControllerInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (!method.getName().startsWith(REQUEST_METHOD_START_NAME)) {
            return method.invoke(target, args);
        }

        Request request = getRequest(args);
        Response response = getResponse(args);
        Execution execution = getExecution(args);
        if (request == null || response == null || execution == null) {
            return method.invoke(target, args);
        }

        // 调用doRequest方法
        if (method.getName().equals(DO_REQUEST_METHOD_NAME)) {
            if (!isTargetRequest(request, request.getMethod())) {
                return method.invoke(target, args);
            }
            doRequest(request, response, execution);
            return null;
        }

        // 调用具体请求方法
        com.yeskery.nut.core.Method httpMethod = com.yeskery.nut.core.Method.valueOf(method.getName().substring(2).toUpperCase());
        if (!isTargetRequest(request, httpMethod)) {
            return method.invoke(target, args);
        }
        doRequest(request, response, execution);
        return null;
    }

    /**
     * 处理请求
     * @param request 请求对象
     * @param response 响应对象
     * @param execution 执行器
     */
    protected abstract void doRequest(Request request, Response response, Execution execution);

    /**
     * 是否是目标请求
     * @param request 请求对象
     * @param method HTTP请求方法
     * @return 是否是目标请求
     */
    protected abstract boolean isTargetRequest(Request request, com.yeskery.nut.core.Method method);

    /**
     * 获取请求对象
     * @param args 参数
     * @return 请求对象
     */
    private Request getRequest(Object[] args) {
        for (Object arg : args) {
            if (arg instanceof Request) {
                return (Request) arg;
            }
        }
        return null;
    }

    /**
     * 获取响应对象
     * @param args 参数
     * @return 响应对象
     */
    private Response getResponse(Object[] args) {
        for (Object arg : args) {
            if (arg instanceof Response) {
                return (Response) arg;
            }
        }
        return null;
    }

    /**
     * 获取执行器对象
     * @param args 参数
     * @return 执行器对象
     */
    private Execution getExecution(Object[] args) {
        for (Object arg : args) {
            if (arg instanceof Execution) {
                return (Execution) arg;
            }
        }
        return null;
    }
}
